package cn.wolfcode.business.service.impl;

import cn.wolfcode.business.domain.BusAudit;
import cn.wolfcode.business.domain.BusBpmnInfo;
import cn.wolfcode.business.mapper.BusBpmnInfoMapper;
import cn.wolfcode.business.service.BusBpmnInfoService;
import lombok.Builder;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.image.ProcessDiagramGenerator;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.bcel.generic.NEW;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.reactive.GenericReactiveTransaction;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.http.HttpResponse;
import java.util.Collections;
import java.util.Date;
import java.util.List;


@Service
public class BusBpmnInfoServiceImpl implements BusBpmnInfoService {
    @Autowired
    BusBpmnInfoMapper busBpmnInfoMapper;
    @Autowired
    RepositoryService repositoryService;
    @Autowired
    RuntimeService runtimeService;
    @Autowired
    private List list;

    @Override
    public List<BusBpmnInfo> getBpmnInfoList() {
        return busBpmnInfoMapper.getBpmnInfoList();
    }

    /**
     * @param bpmnType 部署的流程类型
     * @param file     部署的流程定义文件
     * @param info     描述信息
     * @return
     */
    @Override
    public Integer add(Integer bpmnType, MultipartFile file, String info) throws IOException {
        //1.参数合理化校验
        if (bpmnType == null || file == null || info == null) {
            throw new RuntimeException("非法参数！");
        }
        //2.对文件的格式，大小进行校验
        //获取文件名
        String originalFilename = file.getOriginalFilename();
        //获取文件后缀名
        String lastFileName = originalFilename.substring(originalFilename.lastIndexOf("."));
        if (lastFileName.equalsIgnoreCase("xml") || lastFileName.equalsIgnoreCase("bpmn")) {
            throw new RuntimeException("文件类型不合法！只支持xml或者bpmn的文件！");
        }
        long size = file.getSize();
        if (size > 10 * 1024 * 1024) {
            throw new RuntimeException("文件过大!文件最大不能超过10MB");
        }
        //3.通过部署流程定义可以获取到部署流程的id和部署时间
        Deployment deployment = repositoryService.createDeployment()
//                .addInputStream(originalFilename,file.getResource())
                .addInputStream(originalFilename, file.getInputStream()).deploy();
        //4.通过部署的流程定义id获取到流程定义的key和版本号
        String deploymentId = deployment.getId();
        Date deploymentTime = deployment.getDeploymentTime();
        //4.1根据流程定义id获取流程定义的key和版本号
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploymentId).singleResult();
        int version = processDefinition.getVersion();
        String key = processDefinition.getKey();
        //5.封装成一个部署流程定义的对象BusBpmnInfo插入到表中并添加上事物
        BusBpmnInfo busBpmnInfo = new BusBpmnInfo();
        busBpmnInfo.setBpmnLabel(originalFilename);//流程名称
        busBpmnInfo.setBpmnType(bpmnType);//流程类型
        busBpmnInfo.setProcessDefinitionKey(key);//activity流程定义生成的key
        busBpmnInfo.setDeployTime(deploymentTime);//部署时间
        busBpmnInfo.setVersion(version);//版本号
        busBpmnInfo.setInfo(info);//描述信息
        return busBpmnInfoMapper.add(busBpmnInfo);
    }

    /**
     * 撤销流程定义
     *
     * @param id
     * @return
     */
    @Override
    @Transactional
    public Integer delete(Long id) {
        //1.参数合理化验证
        if (id == null) {
            throw new RuntimeException("非法参数！");
        }
        //2.需要删除流程定义同时需要删除业务表中的数据
        BusBpmnInfo busBpmnInfo = busBpmnInfoMapper.selectBusBpmnInfoById(id);
        //2.1根据根据id查询出流程定义的key和版本号删除业务表中--查询出对应的流程定义id
        Integer version = busBpmnInfo.getVersion();//版本号
        String processDefinitionKey = busBpmnInfo.getProcessDefinitionKey();//流程定义的key
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().
                processDefinitionKey(processDefinitionKey)
                .processDefinitionVersion(version).singleResult();
        //2.2根据流程定义的key和版本号删除流程定义--级联删除-》后续在进行优化
        repositoryService.deleteDeployment(processDefinition.getDeploymentId(), true);
        //2.3根据id删除业务表中的数据
        return busBpmnInfoMapper.deleteById(id);
    }

    /**
     * 用于查询流程部署的文件，并使用插件生成流程图
     *
     * @param id   流程定义明细的id
     * @param type 文件类型
     */
    @Override
    public InputStream readResource(Long id, String type) {
        //1.参数合理化校验
        if (id == null || type == null) {
            throw new RuntimeException("非法参数！");
        }
        //2.通过流程定义明细id查询到对应的流程定义的key和版本号
        BusBpmnInfo busBpmnInfo = busBpmnInfoMapper.selectBusBpmnInfoById(id);
        String processDefinitionKey = busBpmnInfo.getProcessDefinitionKey();
        Integer version = busBpmnInfo.getVersion();
        //3.根据key和版本号查询流程定义对象
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(processDefinitionKey)
                .processDefinitionVersion(version)
                .singleResult();
        //4. 根据流程定义对象  和   type
        if (type.equalsIgnoreCase("xml")) {
            //查询xml文件,需要一个部署的id和文件名称
            String resourceName = processDefinition.getResourceName();
            String deploymentId = processDefinition.getDeploymentId();
            return repositoryService.getResourceAsStream(deploymentId, resourceName);
        }
        //5.如果是png文件需要使用插件生成流程图，需要六个参数
        //创建一个插件对象
        DefaultProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();

        //5.1获取BpmnModel对象
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
        //5.2获取当前活动的节点
        return processDiagramGenerator
                .generateDiagram(
                        bpmnModel,
                        Collections.emptyList(),
                        Collections.emptyList(),
                        "宋体", "宋体", "宋体"
                );
    }

    @Override
    public BusBpmnInfo selectProcessInstanceByBpmnType(Integer flowAuditType) {
        return busBpmnInfoMapper.selectProcessInstanceByBpmnType(flowAuditType);
    }


}
